﻿using System;
using System.Gadgets;
using ScriptFX;
using ScriptFX.Net;
using System.XML;
using System.DHTML;

namespace MythtvGadget
{
    public class MythtvStatusResult
    {
        public bool Success;
        public string SuccessMessage;

        public string MythVersion;
        public DateTime Updated;

        public int EncodersIdle = 0;
        public int EncodersBusy = 0;

        public int GuideDays;
        public string GuideStatus;

        public int DriveTotalUsed;
        public int DriveTotalFree;

        public Program[] Programs;

        public int DriveTotalFreeGb
        {
            get
            {
                return Math.Floor(DriveTotalFree / 1024);
            }
        }

        public int DriveTotalUsedPercent
        {
            get
            {
                return Math.Floor(100 * (DriveTotalUsed / (DriveTotalUsed + DriveTotalFree)));
            }
        }

		public bool ParseOk = false;
        public string DebugMessage;

        public MythtvStatusResult(IHTTPResponse response)
        {
            Success = (response.StatusCode == HTTPStatusCode.OK);

			if (!Success)
			{
				DebugMessage = "Request Failed";
			}
            else
            {
				ParseResponse(response);
            }
        }

		private void ParseResponse(IHTTPResponse response)
		{
			try
			{
				XMLDocument dom;
				// If we are talking to a "real" Myth status url then .GetXML will return a DOM.
				// Else if we are testing and just accessing a file on a webserver
				// then .GetXML() will return null and we need to use GetText() instead.
				dom = response.GetXML();

				if (dom == null)
					dom = XMLDocumentParser.Parse(response.GetText());

				XMLNode nodStatus = dom.SelectSingleNode("/Status");

				MythVersion = nodStatus.Attributes.GetNamedItem("version").Text;

				// ISODate attribute only exists in MythTv 0.21 and later.
				if (nodStatus.Attributes.GetNamedItem("ISODate") != null)
					Updated = Utilities.XMLDateTimeParser(nodStatus.Attributes.GetNamedItem("ISODate").Text);
				else
				{
					Updated = DateTime.Now;
				}

				XMLNodeList nlEncoders = dom.SelectNodes("/Status/Encoders/Encoder");

				for (int i = 0; i < nlEncoders.Length; i++)
				{
					if (nlEncoders[i].Attributes.GetNamedItem("state").Text == "0")
						EncodersIdle++;
					else
						EncodersBusy++;
				}

				XMLNodeList nlPrograms = dom.SelectNodes("/Status/Scheduled/Program");
				Programs = new Program[nlPrograms.Length];

				for (int i = 0; i < nlPrograms.Length; i++)
				{
					Program p = new Program(nlPrograms[i]);
					Programs[i] = p;
				}

				XMLNode nodGuide = dom.SelectSingleNode("/Status/MachineInfo/Guide");
				GuideDays = (int)int.Parse(nodGuide.Attributes.GetNamedItem("guideDays").Text);
				GuideStatus = nodGuide.Attributes.GetNamedItem("status").Text;

				XMLNode nodStorage = dom.SelectSingleNode("/Status/MachineInfo/Storage");

				int mythVersionNumber = (int)int.Parse(MythVersion.Split('.')[1]);

				if (mythVersionNumber >= 22)
				{
					XMLNode nodTotal = nodStorage.SelectSingleNode("Group[@dir=\"TotalDiskSpace\"]");
					DriveTotalFree = (int)int.Parse(nodTotal.Attributes.GetNamedItem("free").Text);
					DriveTotalUsed = (int)int.Parse(nodTotal.Attributes.GetNamedItem("used").Text);

				}
				else if (mythVersionNumber == 21)
				{
					DriveTotalFree = (int)int.Parse(nodStorage.Attributes.GetNamedItem("drive_total_free").Text);
					DriveTotalUsed = (int)int.Parse(nodStorage.Attributes.GetNamedItem("drive_total_used").Text);
				}
				else // 0.20 ?
				{
					XMLNode nodTotalFree = nodStorage.Attributes.GetNamedItem("_total_free");

					if (nodTotalFree != null)
					{
						// Previous mythbackends appear to have a different attribute name
						DriveTotalFree = (int)int.Parse(nodStorage.Attributes.GetNamedItem("_total_free").Text);
						DriveTotalUsed = (int)int.Parse(nodStorage.Attributes.GetNamedItem("_total_used").Text);
					}
				}

				ParseOk = true;
			}
			catch (Exception ex)
			{
				DebugMessage = "Parse Failed<br>" + ex.Message;
			}
		}
    }
}
